home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Magazine / Online / QMail / source / qmail-qmtpd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-15  |  6.6 KB  |  282 lines

  1. #include "stralloc.h"
  2. #include "substdio.h"
  3. #include "subfd.h"
  4. #include "qmail.h"
  5. #include "now.h"
  6. #include "str.h"
  7. #include "fmt.h"
  8. #include "env.h"
  9. #include "sig.h"
  10. #include "auto_qmail.h"
  11. #include "now.h"
  12. #include "datetime.h"
  13. #include "date822fmt.h"
  14. #include "readwrite.h"
  15. #include "control.h"
  16. #include "constmap.h"
  17. #include "received.h"
  18.  
  19. struct qmail qqt;
  20.  
  21. void dropped() { _exit(0); }
  22. void badproto() { _exit(100); }
  23. void resources() { _exit(111); }
  24. void sigalrm() { _exit(111); }
  25.  
  26. unsigned long getlen()
  27. {
  28.  unsigned long len;
  29.  char ch;
  30.  
  31.  len = 0;
  32.  for (;;)
  33.   {
  34.    if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  35.    if (ch == ':') return len;
  36.    if (len > 200000000) resources();
  37.    len = 10 * len + (ch - '0');
  38.   }
  39. }
  40.  
  41. void getcomma()
  42. {
  43.  char ch;
  44.  
  45.  if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  46.  if (ch != ',') badproto();
  47. }
  48.  
  49. struct datetime dt;
  50. char buf[1000];
  51. char buf2[100];
  52.  
  53. char *remotehost;
  54. char *remoteinfo;
  55. char *remoteip;
  56. char *local;
  57.  
  58. stralloc failure = {0};
  59.  
  60. int flagrcpthosts;
  61. stralloc rcpthosts = {0};
  62. struct constmap maprcpthosts;
  63. char *relayclient;
  64. int relayclientlen;
  65.  
  66. int addrallowed(buf,len) char *buf; int len;
  67. {
  68.  int j;
  69.  if (!flagrcpthosts) return 1;
  70.  j = byte_rchr(buf,len,'@');
  71.  if (j >= len) return 1;
  72.  if (constmap(&maprcpthosts,buf + j + 1,len - j - 1)) return 1;
  73.  for (;j < len;++j)
  74.    if (buf[j] == '.')
  75.      if (constmap(&maprcpthosts,buf + j,len - j)) return 1;
  76.  return 0;
  77. }
  78.  
  79. main()
  80. {
  81.  char ch;
  82.  int i;
  83.  unsigned long biglen;
  84.  unsigned long len;
  85.  int flagdos;
  86.  int flagsenderok;
  87.  unsigned long qp;
  88.  char *result;
  89.  
  90.  sig_pipeignore();
  91.  sig_alarmcatch(sigalrm);
  92.  alarm(3600);
  93.  
  94.  if (chdir(auto_qmail) == -1) resources();
  95.  
  96.  if (control_init() == -1) resources();
  97.  flagrcpthosts = control_readfile(&rcpthosts,"control/rcpthosts",0);
  98.  if (flagrcpthosts == -1) resources();
  99.  if (flagrcpthosts)
  100.    if (!constmap_init(&maprcpthosts,rcpthosts.s,rcpthosts.len,0)) resources();
  101.  relayclient = env_get("RELAYCLIENT");
  102.  relayclientlen = relayclient ? str_len(relayclient) : 0;
  103.  
  104.  remotehost = env_get("TCPREMOTEHOST");
  105.  if (!remotehost) remotehost = "unknown";
  106.  remoteinfo = env_get("TCPREMOTEINFO");
  107.  remoteip = env_get("TCPREMOTEIP");
  108.  if (!remoteip) remoteip = "unknown";
  109.  local = env_get("TCPLOCALHOST");
  110.  if (!local) local = env_get("TCPLOCALIP");
  111.  if (!local) local = "unknown";
  112.  
  113.  for (;;)
  114.   {
  115.    if (!stralloc_copys(&failure,"")) resources();
  116.    flagsenderok = 1;
  117.  
  118.    len = getlen();
  119.    if (len == 0) badproto();
  120.  
  121.    if (qmail_open(&qqt) == -1) resources();
  122.    qp = qmail_qp(&qqt);
  123.  
  124.    if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  125.    --len;
  126.  
  127.    if (ch == 10) flagdos = 0;
  128.    else if (ch == 13) flagdos = 1;
  129.    else badproto();
  130.  
  131.    received(&qqt,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0);
  132.  
  133.    /* XXX: check for loops? only if len is big? */
  134.  
  135.    if (flagdos)
  136.      while (len > 0)
  137.       {
  138.        if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  139.        --len;
  140.        while ((ch == 13) && len)
  141.         {
  142.          if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  143.          --len;
  144.          if (ch == 10) break;
  145.          qmail_put(&qqt,"\015",1);
  146.         }
  147.        qmail_put(&qqt,&ch,1);
  148.       }
  149.    else
  150.      while (len > 0) /* XXX: could speed this up, obviously */
  151.       {
  152.        if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  153.        --len;
  154.        qmail_put(&qqt,&ch,1);
  155.       }
  156.    getcomma();
  157.  
  158.    len = getlen();
  159.  
  160.    if (len >= 1000)
  161.     {
  162.      buf[0] = 0;
  163.      flagsenderok = 0;
  164.      for (i = 0;i < len;++i)
  165.        if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  166.     }
  167.    else
  168.     {
  169.      for (i = 0;i < len;++i)
  170.       {
  171.        if (substdio_get(subfdinsmall,buf + i,1) < 1) dropped();
  172.        if (!buf[i]) flagsenderok = 0;
  173.       }
  174.      buf[len] = 0;
  175.     }
  176.    getcomma();
  177.  
  178.    qmail_from(&qqt,buf);
  179.    if (!flagsenderok) qmail_fail(&qqt);
  180.  
  181.    biglen = getlen();
  182.    while (biglen > 0)
  183.     {
  184.      if (!stralloc_append(&failure,"")) resources();
  185.  
  186.      len = 0;
  187.      for (;;)
  188.       {
  189.        if (!biglen) badproto();
  190.        if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  191.        --biglen;
  192.        if (ch == ':') break;
  193.        if (len > 200000000) resources();
  194.        len = 10 * len + (ch - '0');
  195.       }
  196.      if (len >= biglen) badproto();
  197.      if (len + relayclientlen >= 1000)
  198.       {
  199.        failure.s[failure.len - 1] = 'L';
  200.        for (i = 0;i < len;++i)
  201.          if (substdio_get(subfdinsmall,&ch,1) < 1) dropped();
  202.       }
  203.      else
  204.       {
  205.        for (i = 0;i < len;++i)
  206.         {
  207.          if (substdio_get(subfdinsmall,buf + i,1) < 1) dropped();
  208.          if (!buf[i]) failure.s[failure.len - 1] = 'N';
  209.         }
  210.        buf[len] = 0;
  211.  
  212.        if (relayclient)
  213.      str_copy(buf + len,relayclient);
  214.        else
  215.      if (!addrallowed(buf,len)) failure.s[failure.len - 1] = 'D';
  216.  
  217.        if (!failure.s[failure.len - 1])
  218.      qmail_to(&qqt,buf);
  219.       }
  220.      getcomma();
  221.      biglen -= (len + 1);
  222.     }
  223.    getcomma();
  224.  
  225.    switch(qmail_close(&qqt))
  226.     {
  227.      case 0: result = 0; break;
  228.      case QMAIL_WAITPID: result = "Zqq waitpid surprise (#4.3.0)"; break;
  229.      case QMAIL_CRASHED: result = "Zqq crashed (#4.3.0)"; break;
  230.      case QMAIL_USAGE: result = "Zqq usage surprise (#4.3.0)"; break;
  231.      case QMAIL_SYS: result = "Zqq system error (#4.3.0)"; break;
  232.      case QMAIL_READ: result = "Zqq read error (#4.3.0)"; break;
  233.      case QMAIL_WRITE: result = "Zqq write error or disk full (#4.3.0)"; break;
  234.      case QMAIL_NOMEM: result = "Zqq out of memory (#4.3.0)"; break;
  235.      case QMAIL_EXECSOFT: result = "Zcould not exec qq (#4.3.0)"; break;
  236.      case QMAIL_TIMEOUT: result = "Zqq timeout (#4.3.0)"; break;
  237.      case QMAIL_TOOLONG: result = "Dqq toolong surprise (#5.1.3)"; break;
  238.      default: result = "Zqq internal bug (#4.3.0)"; break;
  239.     }
  240.  
  241.    if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)";
  242.  
  243.    if (result)
  244.      len = str_len(result);
  245.    else
  246.     {
  247.      /* success! */
  248.      len = 0;
  249.      len += fmt_str(buf2 + len,"Kok ");
  250.      len += fmt_ulong(buf2 + len,(unsigned long) now());
  251.      len += fmt_str(buf2 + len," qp ");
  252.      len += fmt_ulong(buf2 + len,qp);
  253.      buf2[len] = 0;
  254.      result = buf2;
  255.     }
  256.      
  257.    len = fmt_ulong(buf,len);
  258.    buf[len++] = ':';
  259.    len += fmt_str(buf + len,result);
  260.    buf[len++] = ',';
  261.  
  262.    for (i = 0;i < failure.len;++i)
  263.      switch(failure.s[i])
  264.       {
  265.        case 0:
  266.          if (substdio_put(subfdoutsmall,buf,len) == -1)
  267.            dropped();
  268.      break;
  269.        case 'D':
  270.          if (substdio_puts(subfdoutsmall,"66:Dsorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),") == -1)
  271.        dropped();
  272.      break;
  273.        default:
  274.          if (substdio_puts(subfdoutsmall,"46:Dsorry, I can't handle that recipient (#5.1.3),") == -1)
  275.        dropped();
  276.      break;
  277.       }
  278.  
  279.    /* subfdoutsmall will be flushed when we read from the network again */
  280.   }
  281. }
  282.